package edu.towson.cosc.cosc455.echapp1.markdowncompiler;

import java.util.HashSet;

import edu.towson.cosc.cosc455.interfaces.LexicalAnalyzer;

public class MyLexicalAnalyzer implements LexicalAnalyzer {
	
	String nextCharacter = "";
	int currentPosition = 0;
	public static final String NEWLINE = System.getProperty("line.separator");
	int EOF = 0;
	HashSet <String> tags = new HashSet <String> ();
	
	

	@Override
	public void getNextToken() {
		int checker = 0;
		if (nextCharacter.equals("#")){
			while(!Compiler.token.equalsIgnoreCase("#NEWLINE") && !Compiler.token.equalsIgnoreCase("#VALUE") && //3 ONE WORD TOKENS
					!Compiler.token.equalsIgnoreCase("#NAME") && !Compiler.token.equalsIgnoreCase("#START ") && 
					!Compiler.token.equalsIgnoreCase("#END ")){
				addCharacter();
				checker++;
				if(checker >= 8){
					if(lookupToken()== false){
						System.out.println("The token " + Compiler.token + " is not a valid token!");
						System.exit(2);
					}
				}
				/************************************************************************************
				 * Checker is equal to the number of characters on the token prior to the space.    *
				 * This should never be greater than the eight characters in "#NEWLINE"             *
				 * If it is, then we have an invalid token. If it's exactly eight then there is     *
				 * a chance that the tag could be #NEWLINE, so lookup token would return true       *
				 * and the program would continue                                                   *
				 ************************************************************************************/
				getCharacter(); //When the while loop terminates, this should be the character that is checked by the next while loop
			}
			if(Compiler.token.equalsIgnoreCase("#NEWLINE") || Compiler.token.equalsIgnoreCase("#NAME")
					||  Compiler.token.equalsIgnoreCase("#VALUE")){
				checker = 0; //A valid token was found so we reset checker
				return;
			}
				
			else{ //We either have "#START " or "#END "
				checker = 0; //So reset our checker
				while (isSpace(nextCharacter) == false && isNewline(nextCharacter) == false){ //the end of a start tag is likely to be cut by a space, the end of an end tag by a newline
					addCharacter();
					getCharacter();
				}
				if(lookupToken()== false){
					System.out.println("The token " + Compiler.token + " is not a valid token!");
					System.exit(2);
				}
				else{
				return;
			}
			}
		}
		else{
			while(!nextCharacter.equals("#")){ //this isn't a tag, collect until we find one
				addCharacter();
				getCharacter();
			}
			return;
		}
	}
	/**
	 * This uses the current position and a substring to obtain
	 * the next character. In addition, if the position is at the very
	 * end of the string, it sets an integer to 1, denoting the EOF
	 * When set to 1, the end of file is expected
	 */
	@Override

	public void getCharacter() {
		if(currentPosition < Compiler.filetext.length()-1){
		nextCharacter = Compiler.filetext.substring(currentPosition, currentPosition+1);
		currentPosition++;
		return;
		}
		else{
			nextCharacter = Compiler.filetext.substring(currentPosition);
			EOF = 1;
			return;
		}
	}
	/**
	 * Concats whatever is in the nextCharacter with the current token	
	 */
	@Override
	
	public void addCharacter() {
		Compiler.token = Compiler.token.concat(nextCharacter);
		
	}

	@Override
	public boolean isSpace(String c) {
		if(c.equalsIgnoreCase(" "))
			return true;
		else
		return false;
	}
	@Override
	public boolean isNewline(String c){
		if (c.equalsIgnoreCase(NEWLINE))
			return true;
		else
			return false;
	}
	/**
	 * Returns true if the token is in the hashset or empty.
	 * As the tokens in the hashset are all uppercase
	 * the token being checked is also converted to uppercase
	 */
	@Override
	public boolean lookupToken() {
		
		if(tags.contains(Compiler.token.toUpperCase()) || Compiler.token.isEmpty())
			return true;
		else
			return false;
	}
	
	@Override
	/**
	 * This is used to check to make sure the tags are valid by adding them
	 * to a collection
	 */
	public void addTags(){
		tags.add("#START DOCUMENT");
		tags.add("#END DOCUMENT");
		tags.add("#START BOLD");
		tags.add("#END BOLD");
		tags.add("#START PARAGRAPH");
		tags.add("#END PARAGRAPH");
		tags.add("#START ITALICS");
		tags.add("#END ITALICS");
		tags.add("#START HEAD");
		tags.add("#END HEAD");
		tags.add("#START TITLE");
		tags.add("#END TITLE");
		tags.add("#START LIST");
		tags.add("#END LIST");
		tags.add("#START ITEM");
		tags.add("#END ITEM");
		tags.add("#NEWLINE");
		tags.add("#START AUDIO");
		tags.add("#END AUDIO");
		tags.add("#START VIDEO");
		tags.add("#END VIDEO");
		tags.add("#START DEFINE");
		tags.add("#NAME");
		tags.add("#VALUE");
		tags.add("#END DEFINE");
		tags.add("#START USE");
		tags.add("#END USE");
		return;
	}
	

}
